package vashion.azeroth.api.controller.wukong;

import com.google.common.base.Strings;

import org.codehaus.jackson.map.util.JSONPObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import vashion.azeroth.api.controller.base.BaseController;
import vashion.azeroth.common.im.AppKeys;
import vashion.azeroth.common.im.LoginSH256Util;
import vashion.azeroth.contant.GenericErrorEnum;
import vashion.azeroth.core.personal.pojo.PersonalMember;
import vashion.azeroth.core.result.ApiResult;
import vashion.azeroth.core.service.PersonalMemberService;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

/**
 * 悟空
 * Created by xiaonan on 15/11/23.
 */
@Controller
@RequestMapping("/im")
public class ImController extends BaseController {

	private static final Logger logger = LoggerFactory.getLogger(ImController.class);
	@Autowired
	private PersonalMemberService<PersonalMember> memberService;

	@RequestMapping("/im/imLogin")
	public
	@ResponseBody
	Object login( @RequestParam PersonalMember member, @RequestParam String devType,
				 @RequestParam(required = false) String callback) {

		AppLoginResultModel appLoginResultModel = new AppLoginResultModel();
		if (null == member) {
			return ApiResult.newErrorResult(
					GenericErrorEnum.NOT_EMPTY.getErrorCode(), "参数"
							+ GenericErrorEnum.NOT_EMPTY.getErrorMessage());
		}
		String username = member.getMemberName();
		String password = member.getMemberPwd();
        /*------ 应用自身的登录逻辑 start-----*/
		//下面的checkAccount\getOpenId\genAppAccessToken 有可能在真实应用中合并优化
		if (!checkAccount(member)) {
			appLoginResultModel.setIsSuccess(false);
			//设置 errorCode ,设置 errMsg, etc.

			return appLoginResultModel;

		}
//		long openId = getOpenId(username, password);
		long openId = member.getMemberId();
		if (openId == 0) {
			appLoginResultModel.setIsSuccess(false);
			//设置 errorCode ,设置 errMsg, etc.

			return appLoginResultModel;
		}
		//真实应用可能会维持一个有效时间内的会话与token相对应，用于客户端访问app内的其他api.
		//本demo主要表达的是如何访问IM服务器，所以此处省略会话和token的管理
		String appAccessToken = genAppAccessToken(username, password);
		if (Strings.isNullOrEmpty(appAccessToken)) {
			appLoginResultModel.setIsSuccess(false);
			//设置 errorCode ,设置 errMsg, etc.

			return appLoginResultModel;
		}
		appLoginResultModel.setIsSuccess(true);

		appLoginResultModel.setAppAccessToken(appAccessToken);

        /*------ 应用自身的登录逻辑 end-----*/

        /*------ im签名逻辑 start-----*/

		String appKey = AppKeys.getAppKeyByDevType(devType);
		if (Strings.isNullOrEmpty(appKey)) {
			appLoginResultModel.setIsSuccess(false);
			//设置 errorCode ,设置 errMsg, etc.
			return appLoginResultModel;
		}
		String appSecret = AppKeys.getAppSecret(appKey);

		if (Strings.isNullOrEmpty(appSecret)) {
			appLoginResultModel.setIsSuccess(false);
			//设置 errorCode ,设置 errMsg, etc.
			return appLoginResultModel;
		}
		LoginSH256Util.ImSignModel signModel = LoginSH256Util.getLoginModel(appKey, appSecret, openId);
		appLoginResultModel.setIsSuccess(true);
		appLoginResultModel.setImSignModel(signModel);
        /*------ im签名逻辑 end-----*/


		if (!Strings.isNullOrEmpty(callback)) {
			return new JSONPObject(callback, appLoginResultModel);
		} else {
			return appLoginResultModel;
		}
	}


	@RequestMapping("/im/imRegiest")
	public
	@ResponseBody
	Object reg(@RequestParam PersonalMember member, @RequestParam String devType,
			   @RequestParam(required = false) String callback) {
		if (null == member) {
			return ApiResult.newErrorResult(
					GenericErrorEnum.NOT_EMPTY.getErrorCode(), "参数"
							+ GenericErrorEnum.NOT_EMPTY.getErrorMessage());
		}
		String username = member.getMemberName();
		String password = member.getMemberPwd();
		if (regist(username, password)) {

			return login(member, devType, callback);
		} else {
			AppLoginResultModel appLoginResultModel = new AppLoginResultModel();
			appLoginResultModel.setIsSuccess(false);
			/**--真实应用应该设置相应注册错误码---**/
			return appLoginResultModel;

		}
	}

	/**
	 * 注册
	 *
	 * @param username
	 * @param pasword
	 */
	private boolean regist(String username, String pasword) {
		//实现一般是检查重复username,如果重复应该返回相应错误码
		//入库
		return true;
	}

	private boolean checkAccount(PersonalMember member) {
		//加载用户数据 (app可能从 database中加载)， 检查用户名存在及与密码的匹配
		try {
			ApiResult<PersonalMember> result = memberService.checkMember(member);
			return result.isSuccess();
		} catch (Exception e) {
			logger.error("checkAccount exception,e:{},userId:{},userName:{}",e,member.getMemberId(),member.getMemberName());
			return false;
		}
	}

	private long getOpenId(String username, String pwd) {
		String srcStr = username + "_" + pwd;

		try {
			byte[] bytes = srcStr.getBytes("utf8");
			byte[] md5Bytes = md5(bytes);
			byte[] shortBytes = Arrays.copyOf(md5Bytes, 4);
			long openId = byteToInt(shortBytes);
			return openId;
		} catch (Exception e) {
			logger.error("getOpenId exception,e:{},userName:{}", e, username);
		}

		return 0;

	}

	private String genAppAccessToken(String username, String pwd) {
		long openId = getOpenId(username, pwd);

		return "demo-app-at-" + openId;//return some outh token;
	}

	private byte[] md5(byte[] srcBytes) {
		MessageDigest messageDigest = null;
		try {
			messageDigest = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		messageDigest.update(srcBytes);
		// 获得密文
		byte[] md = messageDigest.digest();
		return md;
	}

	class AppLoginResultModel {
		boolean isSuccess;
		String appAccessToken;//独立应用中授权使用应用接口的票
		LoginSH256Util.ImSignModel imSignModel;

		public LoginSH256Util.ImSignModel getImSignModel() {
			return imSignModel;
		}

		public void setImSignModel(LoginSH256Util.ImSignModel imSignModel) {
			this.imSignModel = imSignModel;
		}

		public boolean isSuccess() {
			return isSuccess;
		}

		public void setIsSuccess(boolean isSuccess) {
			this.isSuccess = isSuccess;
		}

		public String getAppAccessToken() {
			return appAccessToken;
		}

		public void setAppAccessToken(String appAccessToken) {
			this.appAccessToken = appAccessToken;
		}
	}

	private static Long byteToLong(byte[] b) {
		if (b.length != 8) {
			return null;
		}

		final long mask = 0xff;
		long temp = 0;
		long n = 0;
		for (int i = 0; i < 8; i++) {
			n <<= 8;
			temp = b[i] & mask;
			n |= temp;
		}
		if (n < 0) {//简单处理，如果最高位是1（负数）则返回绝对值
			n = Math.abs(n);
		}


		return n;
	}

	private static Integer byteToInt(byte[] b) {
		if (b.length != 4) {
			return null;
		}

		final int mask = 0xff;
		int temp = 0;
		int n = 0;
		for (int i = 0; i < 4; i++) {
			n <<= 8;
			temp = b[i] & mask;
			n |= temp;
		}
		if (n < 0) {//简单处理，如果最高位是1（负数）则返回绝对值
			n = Math.abs(n);
		}


		return n;
	}
}
